/*
 * Copyright (c) 2008, Solido Systems
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of Solido Systems nor the names of its contributors may be
 * used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

package com.solidosystems.objectkitchen.client;

import java.io.*;
import java.net.*;
import java.util.*;
import com.solidosystems.objectkitchen.data.*;
import com.solidosystems.objectkitchen.storage.*;

public class StorageConnector implements Storage{
	public static final int OK=0; 
	public static final int ERR=1; 
	
	public static final int QUIT=0;
	public static final int PING=1;
	public static final int GET_DOC=2;
	public static final int PUT_DOC=3;
	public static final int DEL_DOC=4;
	public static final int GET_ATT=5;
	public static final int PUT_ATT=6;
	public static final int DEL_ATT=7;
	
	
	private Socket socket;
	private DataInputStream bufin;
	private DataOutputStream bufout;
	
	public StorageConnector(){
		
	}
	
	public boolean open(){
		return open("127.0.0.1",5771);
	}
	
	public boolean open(String ip){
		return open(ip,5771);
	}
	
	public synchronized boolean open(String ip,int port){
		try{
			socket=new Socket(ip,port);
			bufin=new DataInputStream(new BufferedInputStream(socket.getInputStream()));
			bufout=new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
			return true;
		}catch(Exception e){
			e.printStackTrace();
		}
		return false;
	}
	
	private boolean readOk() throws IOException{
		int result=bufin.readByte();
		return result==OK;
	}
	
	public synchronized Document getOrCreateDocument(String id){
		// Missing implementation
		return null;
	}
	
	public synchronized Document getDocument(String id,int version){
		// Missing implementation
		return null;
	}
	
	public synchronized Document getDocument(String id){
		try{
			bufout.writeByte(GET_DOC);
			bufout.writeUTF(id);
			bufout.flush();
			if(readOk()){
				Document doc=Document.readFromStream(bufin);
				return doc;
			}
		}catch(Exception e){}
		return null;
	}

	public synchronized void putDocument(Document doc){
		try{
			bufout.writeByte(PUT_DOC);
			doc.writeToStream(bufout);
			bufout.flush();
			if(readOk()){
				// return true;
			}
		}catch(Exception e){}
		// return false;
		// we should add error handling
	}
	
	public synchronized void deleteDocument(String id){
		try{
			bufout.writeByte(DEL_DOC);
			bufout.writeUTF(id);
			bufout.flush();
			if(readOk()){
				// return true;
			}
		}catch(Exception e){}
		// return false;
		// we should add error handling
	}
	
	public synchronized byte[] getAttachment(String id,String title){
		try{
			bufout.writeByte(GET_ATT);
			bufout.writeUTF(id);
			bufout.writeUTF(title);
			bufout.flush();
			if(readOk()){
				int size=bufin.readInt();
				byte[] buf=new byte[size];
				bufin.readFully(buf);
				return buf;
			}
		}catch(Exception e){}
		return null;
	}
	
	public synchronized void putAttachment(String id,String title,byte[] buf){
		try{
			bufout.writeByte(PUT_ATT);
			bufout.writeUTF(id);
			bufout.writeUTF(title);
			bufout.flush();
			if(readOk()){
				bufout.writeInt(buf.length);
				bufout.write(buf,0,buf.length);
				bufout.flush();
				if(readOk()){
					// return true;
				}
			}
		}catch(Exception e){}
		// return false;
		// we should add error handling
	}
	
	public synchronized void deleteAttachment(String id,String title){
		try{
			bufout.writeByte(DEL_ATT);
			bufout.writeUTF(id);
			bufout.writeUTF(title);
			bufout.flush();
			if(readOk()){
				// return true;
			}
		}catch(Exception e){}
		// return false;
		// we should add error handling
	}
	
	public synchronized boolean ping(){
		try{
			bufout.writeByte(PING);
			bufout.flush();
			if(readOk())return true;
		}catch(Exception e){}
		return false;
	}
	
	public synchronized void close(){
		try{
			bufout.writeByte(QUIT);
			bufout.flush();
			bufin.readByte();
		}catch(Exception e){}
		try{
			bufin.close();
			bufout.close();
		}catch(Exception e){}
		try{
			socket.close();
		}catch(Exception e){}
	}
	
	public boolean hasDocument(String id) throws IOException{
		// missing implementation
		return true;
	}
}